package cn.biplam.front.component.data.tree;

import java.util.ArrayList;

import cn.biplam.common.client.DataFilter;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.client.Operator;
import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.sqlresult.SqlResult;
import cn.biplam.common.wrapper.tree.TreeNode;
import cn.biplam.common.wrapper.tree.TreeStructre;

/**
 * 基于父子表数据源的树形控件数据操作组件
 * @author XiaoRuxing 2009-6-8下午03:12:18
 * @version 1.0
 */
public class TreeChainData extends TreeData{

	/** 存储父子数据的树形数据结构 */
	private TreeStructre treeData;
	/** 父子表的字段与树字段映射关系 */
	private TreeChainDataMap fieldMap;
	/** 父子关系表数据 */
	private SqlResult finiationData;

	private String nodeId;
	private String nodeLevel;
	private String haveBrother;
	private String haveLBrother;
	private String parentsHaveLBrother;
	private int levelDown;
	private String nodeName;
	private String nodeParent;
	private String parentOpId;
	private String userID;
	private DbResource dbResource;
	private boolean virtualNodeVisiable = false;
	
	/**
	 * 创建父子表数据源的数据控件数据操作类
	 * @param sOperatorID  查询父子表数据的操作ID
	 * @param userID	   用户ID
	 * @param filter       查询父子表数据的过滤器
	 * @param fieldMap     父子表的字段与树字段映射关系
	 * @param levelDown    向下取几级数据 -1 全部 0 当前  1 当前节点下1级 2当前节点向下2级 ... n当前节点向下n级
	 * @param showCurrentNode  是否包含当前节点
	 * @throws ErrorMessage 
	 */
	public TreeChainData(String sOperatorID,
			String userID,
			DataFilter filter,
			TreeChainDataMap fieldMap,
			int levelDown) throws ErrorMessage{
		this(sOperatorID,userID,filter,fieldMap,levelDown,null);
	}

	/**
	 * 创建父子表数据源的数据控件数据操作类
	 * @param sOperatorID  查询父子表数据的操作ID
	 * @param userID	   用户ID
	 * @param filter       查询父子表数据的过滤器
	 * @param fieldMap     父子表的字段与树字段映射关系
	 * @param levelDown    向下取几级数据 -1 全部 0 当前  1 当前节点下1级 2当前节点向下2级 ... n当前节点向下n级
	 * @param showCurrentNode  是否包含当前节点
	 * @throws ErrorMessage 
	 */
	public TreeChainData(String sOperatorID,
			String userID,
			DataFilter filter,
			TreeChainDataMap fieldMap,
			int levelDown,
			DbResource dbResource) throws ErrorMessage{
		/** 根据指定的operatorID从数据库中查询出父子表的数据,存入SqlResult */
		filter.put("level_down", TOOLS.intToString(levelDown));
		if(dbResource==null){
			finiationData=Operator.get(sOperatorID, userID, filter).getSelectResult();
		}else{
			finiationData=Operator.get(sOperatorID, userID, filter,dbResource).getSelectResult();
		}
		this.nodeId=filter.getValue(fieldMap.getNodeId());
		this.fieldMap=fieldMap;
		this.levelDown=levelDown;
		this.userID = userID;
	}
	
	/**
	 * 创建父子表数据源的数据控件数据操作类
	 * @param finiationData  返回的父子树结果集
	 * @param userID 用户ID
	 * @param filter 查询父子表数据的过滤器
	 * @param fieldMap 父子表的字段与树字段映射关系
	 * @param levelDown 向下取几级数据 -1 全部 0 当前  1 当前节点下1级 2当前节点向下2级 ... n当前节点向下n级
	 * @throws ErrorMessage 
	 */
	public TreeChainData(SqlResult finiationData,
						 String userID,
						 String nodeId,
						 TreeChainDataMap fieldMap,
						 int levelDown) throws ErrorMessage{
		/** 根据指定的operatorID从数据库中查询出父子表的数据,存入SqlResult */
		this.finiationData = finiationData;
		this.nodeId=nodeId;
		this.fieldMap=fieldMap;
		this.levelDown=levelDown;
		this.userID = userID;
	}

	/**
	 * 设置树形控件的数据源
	 * @param nodeLevel        		 当期节点级别
	 * @param haveBrother            当前节点是否有哥哥
	 * @param haveLBrother           当前节点是否有弟弟
	 * @param parentsHaveLBrother    当前节点的父亲们是否有弟弟
	 * @throws ErrorMessage 
	 */
	public void setData(String nodeLevel,
			String haveBrother,
			String haveLBrother,
			String parentsHaveLBrother) throws ErrorMessage{
		this.nodeLevel=nodeLevel;
		this.haveBrother=haveBrother;
		this.haveLBrother=haveLBrother;
		if(!TOOLS.StringIsEmpty(parentsHaveLBrother)){
			this.parentsHaveLBrother=parentsHaveLBrother;
		}
	}

	/**
	 *  设置虚根节点是否显示
	 * @param virtualNodeVisialble
	 */
	public void setVirtualNodeVisiable(boolean virtualNodeVisialble){
		this.virtualNodeVisiable = virtualNodeVisialble;
	}

	/**
	 * 创建树数据
	 */
	public void create() throws ErrorMessage{
		_setTreeStruct();
		switch(levelDown){
		case 0:
			this.rs=this.treeData.getNode(this.nodeId);
			break;
		default:
			this.rs=this.treeData.getChildren(this.nodeId, TOOLS.intToString(levelDown));
		}
		_setVirtualNode();
	}
	
	/**
	 * 设置获取所有父节点的操作ID
	 * @param getParentOpt 获取所有父亲节点操作ID
	 */
	public void setGetParentOpt(String parentOpId){
		this.parentOpId = parentOpId;
	}
	
	/**
	 * 取得需展开节点的所有父亲id
	 * @param extendNodeId 需要展开的节点Id
	 * @param level        需要展开的节点在树中的级别
	 * @return KvMap<父节点id,父节点id>
	 * @throws ErrorMessage 
	 */
	@Override
	public KvMap<String, String> getExtendNodeAllParent(String extendNodeId) throws ErrorMessage {
		DataFilter filter = new DataFilter();
		filter.put(fieldMap.getNodeId(), extendNodeId);
		if(this.parentOpId==null){
			throw new ErrorMessage("Get All Parent OptId have not be setted!");
		}
		OperatorResult rs = Operator.get(this.parentOpId,this.userID , filter,this.dbResource);
		KvMap<String, String> kvParents = null;
		if(rs!=null){
			kvParents = rs.getKvResult();
		}
		return kvParents;
	}
	
	/**
	 * 根据传入的头节点信息生成链表头节点
	 * @return
	 */
	private TreeNode _getHeadNode(){
		TreeNode head=new TreeNode();
		head.setNodeID(this.nodeId);
		head.setNodeName(this.nodeName);
		head.setParent(this.nodeParent);
		if(this.nodeLevel==null){
			this.nodeLevel="1";
		}
		head.setLevel(this.nodeLevel);
		head.setHaveBrother(this.haveBrother);
		head.setHaveLBrother(this.haveLBrother);
		if(this.parentsHaveLBrother!=null&&!"".equals(this.parentsHaveLBrother)){
			String [] parentsLb=this.parentsHaveLBrother.split("_");
			ArrayList<String> parentSibling=new ArrayList<String>();
			TOOLS.stringArrayToList(parentSibling, parentsLb);
			head.setParentSibling(parentSibling);
		}
		return head;
	}

	/**
	 * 将查询出来的父子关系数据封装成树节点数据类
	 * @throws ErrorMessage 
	 */
	private ArrayList<TreeNode> _exchangDataToNode() throws ErrorMessage{
		ArrayList<TreeNode> nodes=new ArrayList<TreeNode>();
		TreeNode node=null;
		String nodeID=null;
		String nodeParent=null;
		String nodeName=null;
		String nodeRealID = null;
		String nodeIDField=fieldMap.getNodeId();
		String nodeParentField=fieldMap.getNodeParent();
		String nodeNameField=fieldMap.getNodeName();
		String nodeRealField = fieldMap.getRealId();
		String operatorType = null;
		String nodeType = null;

		if(TOOLS.StringIsEmpty(nodeRealField)){//如果未设置物理字段设置物理ID为索引ID
			nodeRealField = fieldMap.getNodeId();
		}

		if(nodeIDField==null||nodeParentField==null){
			throw new ErrorMessage(" ID or parentID of the tree is null!");
		}

		if(finiationData==null){
			return nodes;
		}

		for(int i=0;i<finiationData.size();i++){
			node=new TreeNode();
			nodeID=finiationData.get(i, nodeIDField);
			nodeParent=finiationData.get(i, nodeParentField);
			nodeRealID = finiationData.get(i, nodeRealField);
			if(nodeNameField!=null){
				nodeName=finiationData.get(i, nodeNameField);
			}
			operatorType = finiationData.get(i, this.fieldMap.getOperatorType());
			nodeType = finiationData.get(i, this.fieldMap.getNodeType());
			if(nodeID.equals(this.nodeId)){//如果是当前链表的头节点不添加
				this.nodeName=nodeName;
				this.nodeParent=nodeParent;
			}else{
				node=new TreeNode(nodeID,nodeParent,nodeName);
				nodes.add(node);
				node.setNodeCode(nodeRealID);
				node.setNodeType(nodeType);
				node.setOperator(operatorType);
			}
		}
		return nodes;
	}

	/**
	 * 根据树数据生成树的链表
	 * @throws ErrorMessage 
	 */
	private void _setTreeStruct() throws ErrorMessage{
		treeData=new TreeStructre();
		ArrayList<TreeNode> nodes=this._exchangDataToNode();
		treeData.insertHead(this._getHeadNode());
		for(TreeNode node:nodes){
			treeData.insert(node);
		}
	}
	
	/**
	 *  设置虚根节点数据
	 * @throws ErrorMessage
	 */
	private void _setVirtualNode() throws ErrorMessage{
		if(this.virtualNodeVisiable){
			this.vNodeName = nodeName;
		}
	}
}
